package com.crane.oss.web.controller.sys;


import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.validation.Valid;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.session.Session;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.crane.common.core.dto.Response;
import com.crane.common.core.dto.SessParty;
import com.crane.common.core.dto.SessUser;
import com.crane.common.core.dto.SingleResponse;
import com.crane.common.core.exception.AppException;
import com.crane.common.core.exception.BasicErrorCode;
import com.crane.common.framework.shiro.ShiroRedisCache;
import com.crane.common.framework.utils.BeanUtil;
import com.crane.oss.common.bean.request.QueryDynamicCodeRequest;
import com.crane.oss.sys.bean.request.user.ForgetUserPassWordRequest;
import com.crane.oss.sys.bean.request.LoginRequest;
import com.crane.oss.sys.bean.resp.PartyBean;
import com.crane.oss.sys.bean.resp.RoleBean;
import com.crane.oss.sys.bean.resp.UserBean;
import com.crane.oss.enums.DynamicCodeTypeEnum;
import com.crane.oss.common.service.DynamicCodeService;
import com.crane.oss.sys.service.PartyService;
import com.crane.oss.sys.service.RoleService;
import com.crane.oss.sys.service.UserService;
import com.crane.oss.web.BaseBusinessController;
import com.crane.oss.web.support.shiro.UserNamePassWordRealm;
import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.Producer;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;

/**
 * 管理平台用户登录、录出相关服务
 */
@Api(value = "ManagerController", tags = {"管理平台用户登陆、登出接口"})
@Controller
@RequestMapping("/sys/manager")
public class ManagerController extends BaseBusinessController {

    // 代理商登录开关，"OFF"-不可登陆, 不配或其他-可登陆
    protected static final String SWITCH_AGENT_LOGIN = "SWITCH_AGENT_LOGIN";

    private Logger logger = LoggerFactory.getLogger(ManagerController.class);

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private PartyService partyService;

    @Autowired
    private DynamicCodeService dynamicCodeService;

    @Autowired
    private Producer producer;

    /**
     * 用户密码登录
     */
	@ApiOperation(value = "用户登录", notes = "用户登录接口", httpMethod = "POST")
    @ApiImplicitParam(name = "request", value = "请求对象", required = true, dataType = "LoginRequest")
    @ResponseBody
    @PostMapping(value = "/login")
    public SingleResponse login(@RequestBody @Valid LoginRequest request) {

        // 校验用户是否存在
        UserBean userObj = userService.queryUserByName(request.getUsername());
        if (userObj == null) {
            throw new AppException(BasicErrorCode.ENTITY_NOT_EXISTS, "用户");
        }
        // 验证登录验证码
//        QueryDynamicCodeRequest queryDynamiccodeRequest = new QueryDynamicCodeRequest();
//        queryDynamiccodeRequest.setUserId(userObj.getUserName());
//        queryDynamiccodeRequest.setBizType(DynamicCodeTypeEnum.LOGIN_CODE.getValue());
//        queryDynamiccodeRequest.setDynaCode(request.getLoginCode());
//        queryDynamiccodeRequest.setRefNo(userObj.getMobile());
//        // 不抛异常则验证通过
//        dynamicCodeService.validateCode(queryDynamiccodeRequest);



		// 注释掉图形验证码  替换成短信验证码
		Session session = SecurityUtils.getSubject().getSession(false);
		// 调用接口前必须先取得会话，应为验证码是存在会话里的。
		if (null == session) {
            logger.error("未获取到会话id");
			return SingleResponse.buildFailure(BasicErrorCode.SESSION_TIMEOUT);
		}
		String kaptcha = "";
		Object obj = session.getAttribute(Constants.KAPTCHA_SESSION_KEY);
		if (null != obj) {
			kaptcha = obj.toString();
		}
		if (!request.getLoginCode().toLowerCase().equals(kaptcha.toLowerCase())) {
			return SingleResponse.buildFailure("验证码错误");
		}
        //初始化创建Session对象
        SecurityUtils.getSubject().getSession();

        UsernamePasswordToken token = new UsernamePasswordToken(request.getUsername(), request.getPassword(), false, getIpAddr(httpServletRequest));
        try {
            SecurityUtils.getSubject().login(token);
        } catch (AuthenticationException e) {
            logger.error("登录出错", e);
            return SingleResponse.buildFailure(e.getMessage());
        }
        // 刷新权限
        SessUser sessUser = (SessUser) SecurityUtils.getSubject().getPrincipal();
        ShiroRedisCache<Object, Object> cache = (ShiroRedisCache<Object, Object>) ((DefaultWebSecurityManager) SecurityUtils
                .getSecurityManager()).getCacheManager().getCache(UserNamePassWordRealm.class.getName() + ".authorizationCache");
        cache.remove(sessUser.getUserId());

        UserBean userBean = new UserBean();
        BeanUtil.copyProperties(sessUser, userBean);

        // 查询所属角色
        List<Long> roleIdList = new ArrayList<>();
        userBean.setRoleIdList(roleIdList);
        List<RoleBean> roleList = roleService.getUserRole(userBean);
        if (null != roleList && roleList.size() != 0) {
            userBean.setRoleBeanList(roleList);
            for (RoleBean roleBean : roleList) {
                roleIdList.add(roleBean.getId());
            }
        }
        List<PartyBean> partyBeanList = partyService.queryPartyByUserId(userBean.getUserId());
        userBean.setPartyBeanList(partyBeanList);
        PartyBean partyBean=partyBeanList.get(0);
        SessParty sessParty = new SessParty();
        BeanUtil.copyProperties(partyBean, sessParty);
        setParty(sessParty);
        userBean.setPartyId(partyBean.getPartyId());
        userBean.setPartyType(partyBean.getPartyType());
        userBean.setPartyCode(partyBean.getPartyCode());
        userBean.setPartyName(partyBean.getNameCn());
        userBean.setProvinceName(partyBean.getProvinceName());
        userBean.setCityName(partyBean.getCityName());
        userBean.setAreaName(partyBean.getAreaName());
        return SingleResponse.of(userBean);
    }


    @ApiOperation(value = "忘记登录用户密码", notes = "忘记登录用户密码")
    @ApiImplicitParam(name = "request", value = "请求对象", required = true, dataType = "ForgetUserPassWordRequest")
    @ResponseBody
    @PostMapping("/forgetPassword")
    public Response forgetPassword(@RequestBody @Valid ForgetUserPassWordRequest request) throws AppException {
        userService.forgetPassword(request);
        return Response.buildSuccess();
    }

    /**
     * 退出
     */
    @ApiOperation(value = "用户注销", notes = "用户注销", httpMethod = "POST")
    @ResponseBody
    @PostMapping(value = "/logout")
    public Response logout() {
        SecurityUtils.getSubject().logout();
        return Response.buildSuccess();
    }

    /**
     * 登录图形验证码
     */
    @ApiOperation(value = "获取登录图形验证码", notes = "登录之前必须先调用此接口", httpMethod = "GET")
    @GetMapping("/captcha")
    public void captcha() throws ServletException, IOException {
        httpServletResponse.setHeader("Cache-Control", "no-store, no-cache");
        httpServletResponse.setContentType("image/jpeg");
        // 生成文字验证码
        String text = producer.createText();
        logger.info("get captcha text={}",text);
        // 生成图片验证码
        BufferedImage image = producer.createImage(text);
        Session session = SecurityUtils.getSubject().getSession();
        // 保存到shiro session
        session.setAttribute(Constants.KAPTCHA_SESSION_KEY, text);
        ServletOutputStream out = httpServletResponse.getOutputStream();
        ImageIO.setUseCache(false);
        ImageIO.write(image, "jpg", out);
        IOUtils.closeQuietly(out);
    }

    @ApiOperation(value = "切换机构", notes = "切换机构")
    @ResponseBody
    @PostMapping("/changeParty")
    public SingleResponse<UserBean> info(@RequestBody String data) {
        String sid = getParamter(data, "partyId");
        PartyBean partyBean = null;
        List<PartyBean>  partyBeanList = partyService.queryPartyByUserId(getUserId());
        for(PartyBean temp : partyBeanList){
            if(temp.getPartyId().equals(Long.parseLong(sid))){
                partyBean=temp;
            }
        }
        // 刷新权限
        SessUser sessUser = (SessUser) SecurityUtils.getSubject().getPrincipal();
        UserBean userBean = new UserBean();
        BeanUtil.copyProperties(sessUser, userBean);

        // 查询所属角色
        List<Long> roleIdList = new ArrayList<>();
        userBean.setRoleIdList(roleIdList);
        List<RoleBean> roleList = roleService.getUserRole(userBean);
        if (null != roleList && roleList.size() != 0) {
            userBean.setRoleBeanList(roleList);
            for (RoleBean roleBean : roleList) {
                roleIdList.add(roleBean.getId());
            }
        }
        userBean.setPartyBeanList(partyBeanList);
        SessParty sessParty = new SessParty();
        BeanUtil.copyProperties(partyBean, sessParty);
        setParty(sessParty);
        userBean.setPartyId(partyBean.getPartyId());
        userBean.setPartyType(partyBean.getPartyType());
        userBean.setPartyCode(partyBean.getPartyCode());
        userBean.setPartyName(partyBean.getNameCn());
        userBean.setProvinceName(partyBean.getProvinceName());
        userBean.setCityName(partyBean.getCityName());
        userBean.setAreaName(partyBean.getAreaName());
        return SingleResponse.of(userBean);
    }

}
